package com.ktg.mes.wm.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.ktg.common.core.domain.Result;
import com.ktg.common.core.domain.model.SqlResult;
import com.ktg.common.utils.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ktg.common.utils.SecurityUtils;
import com.ktg.mes.md.domain.MdItem;
import com.ktg.mes.md.domain.MdProductStatisticsBom;
import com.ktg.mes.md.service.IMdItemService;
import com.ktg.mes.md.service.IMdProductStatisticsBomService;
import com.ktg.mes.md.service.IMdStatisticsTypeBomService;
import com.ktg.mes.pro.domain.ProItemNeed;
import com.ktg.mes.pro.domain.ProWorkorder;
import com.ktg.mes.pro.service.IProItemNeedService;
import com.ktg.mes.unit.other.SQLListenerInterface;
import com.ktg.mes.unit.other.SQLListenerType;
import com.ktg.mes.util.LGLeftJoinQueryWrapper;
import com.ktg.mes.wm.domain.*;
import com.ktg.mes.wm.service.IWmIssueLineService;
import com.ktg.mes.wm.service.IWmItemRecptLineService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ktg.mes.wm.mapper.WmStockWillOutMapper;
import com.ktg.mes.wm.service.IWmStockWillOutService;



/**
 * 产品出库记录Service业务层处理
 *
 * @author byteco
 * @date 2022-12-15
 */
@Service
public class WmStockWillOutServiceImpl extends ServiceImpl<WmStockWillOutMapper, WmStockWillOut> implements IWmStockWillOutService
{

    @Autowired
    private IMdItemService mdItemService;

    @Autowired
    private IMdProductStatisticsBomService statisticsBomService;

    @Autowired
    private IProItemNeedService proItemNeedService;


    @Autowired
    private IWmIssueLineService wmIssueLineService;

    @Autowired
    private IWmItemRecptLineService itemRecptLineService;

    /**
     * 查询产品出库记录
     *
     * @param entity 产品出库记录
     * @param page 分页对象
     * @return 产品出库记录
     */
    @Override
    public IPage<WmStockWillOut> queryPageList(WmStockWillOut entity, Page<WmStockWillOut> page) {
        QueryWrapper<WmStockWillOut> lqw = new QueryWrapper<WmStockWillOut>(entity);
        lqw.orderByDesc("create_time");
        IPage<WmStockWillOut> pageList = this.page(page, lqw);
        return pageList;
    }

    /**
     * 查询产品出库记录
     *
     * @param entity 产品出库记录
     * @return 产品出库记录
     */
    @Override
    public List<WmStockWillOut> queryList(WmStockWillOut entity) {
        QueryWrapper<WmStockWillOut> lqw = new QueryWrapper<WmStockWillOut>(entity);
        lqw.orderByDesc("create_time");
        return this.list(lqw);
    }

    public WmStockWillOut getInfo(Long id)
    {
        return this.getById(id);
    }


    /**
     * 新增产品出库记录
     *
     * @param entity 产品出库记录
     * @return 结果
     */
    @Override
    public void insert(WmStockWillOut entity)
    {
        entity.setCreateBy(SecurityUtils.getUsername());
        entity.setCreateTime(DateUtils.getNowDate());
        this.save(entity);
    }

    /**
     * 修改产品出库记录
     *
     * @param entity 产品出库记录
     * @return 结果
     */
    @Override
    public boolean update(WmStockWillOut entity)
    {
        entity.setUpdateBy(SecurityUtils.getUsername());
        entity.setUpdateTime(DateUtils.getNowDate());
        return this.updateById(entity);
    }

    /**
     * 批量删除产品出库记录
     *
     * @param recordIds 需要删除的产品出库记录主键
     * @return 结果
     */
    @Override
    public boolean delete(Long[] recordIds)
    {

        return this.removeByIds(Arrays.asList(recordIds));
    }

    /**
     * 删除产品出库记录信息
     *
     * @param recordId 产品出库记录主键
     * @return 结果
     */
    @Override
    public boolean delete(Long recordId)
    {
        return this.removeById(recordId);
    }

    private LambdaQueryWrapper<WmStockWillOut> buildQueryWrapper(WmStockWillOut entity) {
        LambdaQueryWrapper<WmStockWillOut> lqw = Wrappers.lambdaQuery();
                    lqw.eq(StringUtils.isNotBlank(entity.getLinkType()), WmStockWillOut::getLinkType, entity.getLinkType());
                    lqw.eq(StringUtils.isNotBlank(entity.getLinkId()), WmStockWillOut::getLinkId, entity.getLinkId());
                    lqw.eq(StringUtils.isNotBlank(entity.getStockType()), WmStockWillOut::getStockType, entity.getStockType());
                    lqw.eq(StringUtils.isNotBlank(entity.getStockId()), WmStockWillOut::getStockId, entity.getStockId());
                    lqw.eq(entity.getQuantity() != null, WmStockWillOut::getQuantity, entity.getQuantity());
        return lqw;
    }

    /**
     * 使用leftJion 链接查询预出库数量
     * @param stockWillSelectParam
     * @return
     */
    public List<Map> selectLeftJoinStockWillOut(WmStockWillSelectParam stockWillSelectParam){
        return getBaseMapper().selectLeftJoinStockWillOut(stockWillSelectParam);
    }

    @Override
    public List<Map> materStockWithWillOut(String names, String proItemNeedId,long itemId) {
        return getBaseMapper().materStockWithWillOut(names,proItemNeedId,itemId);
    }

    @Override
    public List<Map> materStockWithWillOutWithTp(String names, String proItemNeedId) {
        return getBaseMapper().materStockWithWillOutWithTp(names,proItemNeedId);
    }

    @Override
    public List<Map> materStockWithWillOut2(String names, String likeName) {
        return getBaseMapper().materStockWithWillOut2(names,likeName);
    }

    @Override
    public List<Map> prokorderWithWillOut(String names, String proItemNeedId) {
        return getBaseMapper().prokorderWithWillOut(names,proItemNeedId);
    }

    @Override
    public List<Map> prokorderWithWillOutWithTp(String names, String proItemNeedId) {
        return getBaseMapper().prokorderWithWillOutWithTp(names,proItemNeedId);
    }

    /**
     * 根据库存信息，按统计分类统计预出库数量
     * @param names
     * @param proItemNeedId
     * @return
     */
    public List<Map> materStockAllWillOut(String names,String proItemNeedId){
        return getBaseMapper().materStockAllWillOut(names,proItemNeedId);
    };

    public List<Map> materStockAllWillOutWithTp(String names,String proItemNeedId){
        return getBaseMapper().materStockAllWillOutWithTp(names,proItemNeedId);
    };

    /**
     * 根据工单信息，按统计分类统计预出库数量
     * @param names
     * @param proItemNeedId
     * @return
     */
    public List<Map> prokorderAllWillOut(String names,String proItemNeedId){
        return getBaseMapper().prokorderAllWillOut(names,proItemNeedId);
    };

    public List<Map> prokorderAllWillOutWithTp(String names,String proItemNeedId){
        return getBaseMapper().prokorderAllWillOutWithTp(names,proItemNeedId);
    };

    @Override
    public List<ProItemNeed> relationProItemNeed(String names, String recordId) {
        return getBaseMapper().relationProItemNeed(names,recordId);
    }

    @Override
    public List<ProItemNeed> relationProItemNeedWithTp(String names, String recordId) {
        return getBaseMapper().relationProItemNeedWithTp(names,recordId);
    }

    @Override
    public List<Map> inventoryWarning() {
        return getBaseMapper().inventoryWarning();
    }

    /**
     * 获取预出库数量的状态  code： -1 代表预出数量大于需求数量，0 代表刚刚好 ， 1 代表还欠缺一些预出库数量
     * @param needItemId
     * @param needLinkId
     * @param addStockType
     * @param addStockId
     * @param addCount
     * @return
     */
    public Result isWillOutStatus(Long needItemId,String needLinkId,String addStockType,String addStockId,float addCount){
        //获取产品
        MdItem needItem = mdItemService.getById(needItemId);

        //获取统计分类BOM
        MdProductStatisticsBom statisticsBom = new MdProductStatisticsBom();
        statisticsBom.setItemId(Long.valueOf(needItem.getItemId()));
        QueryWrapper<MdProductStatisticsBom> mdProductBomQueryWrapper = new QueryWrapper<>(statisticsBom);
        List<MdProductStatisticsBom> statisticsBomList = statisticsBomService.list(mdProductBomQueryWrapper);

        String stringNames = "'"+needItem.getProcessProductName()+"'";
        if (statisticsBomList != null && statisticsBomList.size() > 0 ){
            for (int i = 0;i < statisticsBomList.size();i++){
                stringNames += ","+"'"+ statisticsBomList.get(i).getStatisticsName()+"'";
            }
        }


        String material_stock_idKey = null;
        String quantity_onhandKey = "quantity_onhand";
        String process_product_nameKey = "process_product_name";
        String thiswilloutKey = "thiswillout";
        String allwilloutKey = "allwillout";


        List<Map> materStockAllWillOut = materStockWithWillOut(stringNames,needLinkId,needItem.getItemId());
        Map<String,Float> floatMap = new HashMap<>();
        if (materStockAllWillOut != null && materStockAllWillOut.size() > 0){
            for (int i = 0; i < materStockAllWillOut.size(); i++) {
                Map<String,Object> it = materStockAllWillOut.get(i);

                Object process_product_nameObj = it.get(process_product_nameKey);
                String process_product_name = null;
                if (process_product_nameObj != null){
                    process_product_name = process_product_nameObj.toString();
                }

                Object material_stock_idObj1 = it.get("item_code");
                Object material_stock_idObj2 = it.get("warehouse_code");
                Object material_stock_idObj3 = it.get("batch_code");

                String material_stock_id = null;
                if (material_stock_idObj1 != null && material_stock_idObj2 != null && material_stock_idObj3 !=null){
                    material_stock_id = material_stock_idObj1.toString()+":"+material_stock_idObj2.toString()+":"+material_stock_idObj3.toString();
                }

                Object quantity_onhandObj = it.get(quantity_onhandKey);
                float quantity_onhand = 0f;
                if (quantity_onhandObj != null){
                    quantity_onhand = Float.valueOf(quantity_onhandObj.toString()).floatValue();
                }

                Object thiswilloutObj = it.get(thiswilloutKey);
                float thiswillout = 0f;
                if (thiswilloutObj != null){
                    thiswillout = Float.valueOf(thiswilloutObj.toString()).floatValue();
                }

                Object allwilloutObj = it.get(allwilloutKey);
                float allwillout = 0f;
                if (allwilloutObj != null){
                    allwillout = Float.valueOf(allwilloutObj.toString()).floatValue();
                }
                Float ss = floatMap.get(process_product_name);
                if (ss == null){
                    ss = 0F;
                }
                if (addStockType != null && addStockId != null && addStockType.equals("wm_material_stock")
                        && addStockId.equals(String.valueOf(material_stock_id))){
                    float a = allwillout - thiswillout;
                    if (quantity_onhand < a+addCount){
                        return Result.ERROR(-1,"库存数量，不满足预出库数量");
                    }
                    it.put(allwilloutKey,Float.valueOf(a));
                    ss = Float.valueOf(ss.floatValue()+addCount);
                }else {
                    ss = Float.valueOf(ss.floatValue()+thiswillout);
                }
                floatMap.put(process_product_name,ss);

            }
        }

        List<Map> prokorderAllWillOut = prokorderWithWillOut(stringNames,needLinkId);
        material_stock_idKey = "workorder_id";
        quantity_onhandKey = "quantity";
        process_product_nameKey = "process_product_name";
        thiswilloutKey = "thiswillout";
        allwilloutKey = "allwillout";
        if (prokorderAllWillOut != null && prokorderAllWillOut.size() > 0) {
            for (int i = 0; i < prokorderAllWillOut.size(); i++) {
                Map<String,Object> it = prokorderAllWillOut.get(i);

                Object process_product_nameObj = it.get(process_product_nameKey);
                String process_product_name = null;
                if (process_product_nameObj != null){
                    process_product_name = process_product_nameObj.toString();
                }

                Object material_stock_idObj = it.get(material_stock_idKey);
                Long material_stock_id = 0L;
                if (material_stock_idObj != null){
                    material_stock_id = Long.valueOf(material_stock_idObj.toString());
                }

                Object quantity_onhandObj = it.get(quantity_onhandKey);
                float quantity_onhand = 0f;
                if (quantity_onhandObj != null){
                    quantity_onhand = Float.valueOf(quantity_onhandObj.toString()).floatValue();
                }

                Object thiswilloutObj = it.get(thiswilloutKey);
                float thiswillout = 0f;
                if (thiswilloutObj != null){
                    thiswillout = Float.valueOf(thiswilloutObj.toString()).floatValue();
                }

                Object allwilloutObj = it.get(allwilloutKey);
                float allwillout = 0f;
                if (allwilloutObj != null){
                    allwillout = Float.valueOf(allwilloutObj.toString()).floatValue();
                }
                Float ss = floatMap.get(process_product_name);
                if (ss == null){
                    ss = 0F;
                }
                if (addStockType != null && addStockId != null && addStockType.equals("pro_workorder")
                        && addStockId.equals(String.valueOf(material_stock_id))){
                    float a = allwillout - thiswillout;

                    if (quantity_onhand < a+addCount){
                        return Result.ERROR(-1,"排产数量，不满足预出库数量");
                    }

                    it.put(allwilloutKey,Float.valueOf(a));
                    ss = Float.valueOf(ss.floatValue()+addCount);
                }else {
                    ss = Float.valueOf(ss.floatValue()+thiswillout);
                }
                floatMap.put(process_product_name,ss);
            }
        }


        // 完全匹配
        //获取产品
        ProItemNeed proItemNeed = proItemNeedService.getById(Long.valueOf(needLinkId));
        Float fo = floatMap.get(needItem.getProcessProductName());
        if (fo != null){
            if (proItemNeed.getNeedCount().floatValue() < fo.floatValue()){
                return Result.ERROR(-1,"预出库数量不能大于需求数量");
            };
        }else {
            fo = 0F;
        }

        //BOM 剩余数量
        boolean isNeed = false;
        fo = proItemNeed.getNeedCount().floatValue() - fo.floatValue();
        //当剩余需求 大于 0
        if (fo.floatValue() > 0){
            isNeed = true;
        }
        String bomStr = null;
        //判断BOM预出
        for (int i = 0;i < statisticsBomList.size();i++){
            MdProductStatisticsBom bom1 = statisticsBomList.get(i);
            if (i == 0){
                isNeed = false;
            }
            float 剩余量 = bom1.getQuantity().floatValue()*fo.floatValue();

            // 剩余预出库的数量
            Float f = floatMap.get(bom1.getStatisticsName());
            if (f == null){
                f = 0F;
            }

            //处理浮点型进度问题
            int ab = 1000;
            int a = (int)(剩余量*ab);
            int b = (int)(f.floatValue()*ab);

            if(a < b){
                return Result.ERROR(-1,"【"+bom1.getStatisticsName()+"】总预出库数量大于需求的出库数量");
            }else if(a > b && !StringUtils.isEmpty(bom1.getStatisticsName())){
                isNeed = true;
                bomStr = bom1.getStatisticsName();
            }
        }

        if (isNeed){
            return Result.ERROR(1, bomStr+"：未满足需求总量");
        }
        return Result.ERROR(0,"数量刚刚好");
    }


    List<ProWorkorder> sumItemCountWithProWorkorder(String stockId){
        return getBaseMapper().sumItemCountWithProWorkorder(stockId);
    };


    /**
     * 判断已经预出的成品的总预出+当前组装，预入库总数量，是否大于客户需求总量
     * @return
     */
    public SqlResult isStockWillOutBigThanNeed(ProItemNeed proItemNeed, WmItemRecptLine newObj){

        try {
            MdItem item = mdItemService.getById(Long.valueOf(proItemNeed.getItemId()));
            if (item.getProcessProductName() == null){
                return SqlResult.error(item.getItemName()+" 产品未设置BOM",null);
            }

            //判断成品库存是否满足，不管半成品库存
            ItemNeedStockWillOutInfo info = new ItemNeedStockWillOutInfo();
            info.setLinkId(String.valueOf(proItemNeed.getRecordId()));
            info.setInStatisticsName(item.getProcessProductName());
            List<ItemNeedStockWillOutInfo> itemNeedStockWillOutInfoList = getBaseMapper().selectItemNeedStockWillOutInfo(info);
            float allWillCount = 0;
            if (itemNeedStockWillOutInfoList != null && itemNeedStockWillOutInfoList.size() > 0){
                for (ItemNeedStockWillOutInfo outInfo:itemNeedStockWillOutInfoList) {
                    allWillCount += outInfo.getQuantity().floatValue();
                }
            }

            //组装成品，预入库数量
            WmItemRecptLine itemRecptLine = new WmItemRecptLine();
            itemRecptLine.setInType("3");
            itemRecptLine.setItemNeedId(proItemNeed.getRecordId());
            QueryWrapper queryWrapper = new QueryWrapper<>(itemRecptLine);
            if (newObj.getLineId() != null){
                queryWrapper.ne("line_id",newObj.getLineId());
            }
            queryWrapper.select("sum(quantity_recived) as quantity_recived,item_need_id");
            queryWrapper.groupBy("item_need_id");
            itemRecptLine = itemRecptLineService.getOne(queryWrapper);

            float allInCount = 0;
            if (itemRecptLine != null){
                allInCount = itemRecptLine.getQuantityRecived().floatValue();
            }
            if (allWillCount + allInCount + newObj.getQuantityRecived().floatValue() > proItemNeed.getNeedCount().floatValue()){
                return SqlResult.error("组装预入库数量+预出库的库存已经大于客户总需求",null);
            }
        }catch (Exception e){
            e.printStackTrace();
            return SqlResult.error(this.getClass().toString(),newObj);
        }
        return SqlResult.ok(null,null);
    }


    private HashMap<String,HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>>> getWillMap(ProItemNeed proItemNeed){
        //获取所有的预出库信息
        ItemNeedStockWillOutInfo info = new ItemNeedStockWillOutInfo();
        info.setLinkId(String.valueOf(proItemNeed.getRecordId()));
        List<ItemNeedStockWillOutInfo> itemNeedStockWillOutInfoList = getBaseMapper().selectItemNeedStockWillOutInfo(info);

        //优先级，统计分类，item_code,batch_code,warehouse_code
        HashMap<String,HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>>> hashMap1 = new HashMap<>();


        if (itemNeedStockWillOutInfoList != null && itemNeedStockWillOutInfoList.size() > 0){
            for (int i = 0;i < itemNeedStockWillOutInfoList.size();i++){
                ItemNeedStockWillOutInfo outInfo = itemNeedStockWillOutInfoList.get(i);
                //通过统计分类
                HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>> map1 = hashMap1.get(outInfo.getProcessProductName());
                if (map1 == null){
                    map1 = new HashMap<>();
                    hashMap1.put(outInfo.getProcessProductName(),map1);
                }

                HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>> map2 = map1.get(outInfo.getItemCode());
                if (map2 == null){
                    map2 = new HashMap<>();
                    map1.put(outInfo.getItemCode(),map2);
                }

                HashMap<String,ItemNeedStockWillOutInfo> map3 = map2.get(outInfo.getWarehouseCode());
                if (map3 == null){
                    map3 = new HashMap<>();
                    map2.put(outInfo.getWarehouseCode(),map3);
                }

                ItemNeedStockWillOutInfo info1 = map3.get(outInfo.getBatchCode());
                if (info1 == null){
                    map3.put(outInfo.getBatchCode(),outInfo);
                }
            }
        }
        return hashMap1;
    }


    //监听入库记录变化
    @SQLListenerInterface(tableName = "wm_item_recpt_line",listerType = {SQLListenerType.AddBefore,SQLListenerType.ChangeBefore})
    public SqlResult wmItemRecptLineListener(SQLListenerType type, WmItemRecptLine oldObj, WmItemRecptLine newObj) {
        try {
            if (type == SQLListenerType.AddBefore){
                //产品入库
                if (newObj.getInType().equals("2")
                        && newObj.getIsInStock().equals("1")
                        && newObj.getItemNeedId() != null
                        && newObj.getItemNeedId() > 0){

                    float thisCount = newObj.getQuantityRecived().floatValue();
                    WmStockWillOut willOut = new WmStockWillOut();
                    willOut.stockTableClass(ProWorkorder.class,newObj.getWorkorderId());
                    willOut.linkTableClass(ProItemNeed.class,String.valueOf(newObj.getItemNeedId()));
                    QueryWrapper queryWrapper1 = new QueryWrapper<>(willOut);
                    WmStockWillOut oldWOut = getOne(queryWrapper1);
                    if (oldWOut == null){
                        SqlResult.error("预出库记录不存在",newObj);
                    }
                    if (oldWOut.getQuantity().floatValue() <= 0){
                        SqlResult.error("预出库记录已经完全满足",newObj);
                    }

                    //修改生产排产的预出库信息
                    float quantity = oldWOut.getQuantity().floatValue() - thisCount;
                    if (quantity < 0){
                        quantity = 0;
                    }
                    oldWOut.setQuantity(quantity);
                    updateById(oldWOut);

                    WmStockWillOut willOutNew = new WmStockWillOut();
                    willOutNew.stockTableClass(WmMaterialStock.class,newObj.getMaterialStockKey());
                    willOutNew.linkTableClass(ProItemNeed.class,String.valueOf(newObj.getItemNeedId()));

                    QueryWrapper<WmStockWillOut> queryWrapper2 = new QueryWrapper<>(willOutNew);
                    WmStockWillOut oldWillOut = getOne(queryWrapper2);
                    if (oldWillOut != null){
                        quantity = oldWillOut.getQuantity().floatValue()  + thisCount;
                        oldWillOut.setQuantity(quantity);
                        updateById(oldWillOut);
                    }else {
                        willOutNew.setQuantity(thisCount);
                        save(willOutNew);
                    }
                }
                //创建组装入库预先判断预出总量
                else if (newObj.getInType().equals("3")
                        && newObj.getIsInStock().equals("0")
                        && newObj.getItemNeedId() != null
                        && newObj.getItemNeedId() > 0){
                    ProItemNeed proItemNeed = proItemNeedService.getById(newObj.getItemNeedId());
                    return isStockWillOutBigThanNeed(proItemNeed,newObj);
                }
            }else if (type == SQLListenerType.ChangeBefore){
                // 组装未入库，修改数量
                if (newObj.getInType().equals("3")
                        && oldObj.getInType().equals("3")
                        && !oldObj.getIsInStock().equals("1")
                        && !newObj.getIsInStock().equals("1")
                        && oldObj.getItemNeedId() != null
                        && newObj.getItemNeedId() != null
                        && oldObj.getItemNeedId().longValue() == newObj.getItemNeedId().longValue()
                        && newObj.getQuantityRecived().floatValue() != oldObj.getQuantityRecived().floatValue()){
                    ProItemNeed proItemNeed = proItemNeedService.getById(newObj.getItemNeedId());
                    return isStockWillOutBigThanNeed(proItemNeed,newObj);
                }

                //组装入库操作
                if (    newObj.getInType().equals("3")
                        && oldObj.getInType().equals("3")
                        && !oldObj.getIsInStock().equals("1")
                        && newObj.getIsInStock().equals("1")
                        && newObj.getItemNeedId() != null && newObj.getItemNeedId() > 0
                        && oldObj.getItemNeedId().longValue() == newObj.getItemNeedId().longValue()
                ){

                    float thisCount = newObj.getQuantityRecived().floatValue();
                    if (!oldObj.getIsInStock().equals("4")){
                        return SqlResult.error("半成品数量完全匹配组装比例数量才能入库",null);
                    }

                    ProItemNeed proItemNeed = proItemNeedService.getById(newObj.getItemNeedId());

                    //第一步,组装后的成品预出库增加
                    String willOutKey = newObj.getMaterialStockKey();
                    WmStockWillOut willOutChengPin = new WmStockWillOut();
                    willOutChengPin.stockTableClass(WmMaterialStock.class,willOutKey);
                    willOutChengPin.linkTableClass(ProItemNeed.class, newObj.getItemNeedId());
                    WmStockWillOut oldWillOut = getOne(new QueryWrapper<>(willOutChengPin));

                    if (oldWillOut != null){
                        float allCount = oldWillOut.getQuantity().floatValue()+thisCount;
                        oldWillOut.setQuantity(allCount);
                        updateById(oldWillOut);
                    }else {
                        willOutChengPin.setQuantity(thisCount);
                        save(willOutChengPin);
                    }

                    HashMap<String,HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>>>  hashMap1 = getWillMap(proItemNeed);

                    //查询组装领料记录，优先根据领料记录处理预出库数量
                    List<GatherIssueZuZhuangInfo> zuZhuangInfoList = wmIssueLineService.findZuZhuangInfo(newObj.getLineId());

                    //处理预出库数量
                    for (int i = 0; i < zuZhuangInfoList.size(); i++) {
                        GatherIssueZuZhuangInfo item = zuZhuangInfoList.get(i);
                        dealWillOut(hashMap1,item);
                    }
                    return SqlResult.ok("",null);
                }
            }



        }catch (Exception e){
            e.printStackTrace();
           return SqlResult.error(this.getClass().toString(),e);
        }
        return SqlResult.ok(null,null);

    }

    //监听领料,备货
    @SQLListenerInterface(tableName = "wm_issue_line",listerType = {SQLListenerType.AddBefore,SQLListenerType.ChangeBefore,SQLListenerType.DeleteBefore})
    public SqlResult wmIssueLineListener(SQLListenerType type,WmIssueLine oldObj,WmIssueLine newObj) {
        try {

            if (oldObj != null && newObj != null
                    && oldObj.getWarehouseCode().equals(newObj.getWarehouseCode())
//                    && oldObj.getBatchCode().equals(newObj.getBatchCode())
                    && oldObj.getOutType().equals(newObj.getOutType())
                    && oldObj.getOutType().equals("备货")
                    && oldObj.getItemNeedId() != null
                    && newObj.getItemNeedId() != null
//                    && newObj.getItemNeedId().longValue() == oldObj.getItemNeedId().longValue()
            ){
                if (oldObj.getQuantity().floatValue() == newObj.getQuantity().floatValue()){
                    return SqlResult.ok(null,null);
                }
                float sub = newObj.getQuantity().floatValue() - oldObj.getQuantity().floatValue();

                MdItem mdItem = mdItemService.getById(newObj.getItemId());

                HashMap<String,HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>>>  hashMap1 = getWillMap(proItemNeedService.getById(oldObj.getItemNeedId()));

                //查询组装领料记录，优先根据领料记录处理预出库数量
                GatherIssueZuZhuangInfo item = new GatherIssueZuZhuangInfo();
                item.setItemCode(newObj.getItemCode());
                item.setWarehouseCode(newObj.getWarehouseCode());
                item.setBatchCode(newObj.getBatchCode());
                item.setQuantity(new BigDecimal(sub));
                item.setProcessProductName(mdItem.getProcessProductName());
                dealWillOut(hashMap1,item);

            }

            if (oldObj != null
                    && oldObj.getOutType().equals("备货")
//                    && oldObj.getItemNeedId() != null
                    && oldObj.getIsInStock().equals("1")
                    && (newObj == null || ((newObj != null && !newObj.getIsInStock().equals("1"))))
            ){

                float sub = - oldObj.getQuantity().floatValue();

                MdItem mdItem = mdItemService.getById(oldObj.getItemId());

                HashMap<String,HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>>>  hashMap1 = getWillMap(proItemNeedService.getById(oldObj.getItemNeedId()));

                //查询组装领料记录，优先根据领料记录处理预出库数量
                GatherIssueZuZhuangInfo item = new GatherIssueZuZhuangInfo();
                item.setItemCode(oldObj.getItemCode());
                item.setWarehouseCode(oldObj.getWarehouseCode());
                item.setBatchCode(oldObj.getBatchCode());
                item.setQuantity(new BigDecimal(sub));
                item.setProcessProductName(mdItem.getProcessProductName());
                dealWillOut(hashMap1,item);

            }

            if (newObj != null
                    && newObj.getOutType().equals("备货")
                    && newObj.getItemNeedId() != null
                    && newObj.getIsInStock().equals("1")
                    && (oldObj == null || ((oldObj != null && !oldObj.getIsInStock().equals("1"))))
            ){
                if (newObj.getItemId() == null){
                    return SqlResult.error("产品ID不能为空",null);
                }
                float sub = newObj.getQuantity().floatValue();

                MdItem mdItem = mdItemService.getById(newObj.getItemId());
                if (mdItem == null){
                    return SqlResult.error("根据产品ID找不到对应的产品",null);
                }
                if (StringUtil.isEmpty(mdItem.getProcessProductName())){
                    return SqlResult.error("产品未设置统计分类，请先设置统计分类",null);
                }

                HashMap<String,HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>>>  hashMap1 = getWillMap(proItemNeedService.getById(newObj.getItemNeedId()));

                //查询组装领料记录，优先根据领料记录处理预出库数量
                GatherIssueZuZhuangInfo item = new GatherIssueZuZhuangInfo();
                item.setItemCode(newObj.getItemCode());
                item.setWarehouseCode(newObj.getWarehouseCode());
                item.setBatchCode(newObj.getBatchCode());
                item.setQuantity(new BigDecimal(sub));
                item.setProcessProductName(mdItem.getProcessProductName());
                dealWillOut(hashMap1,item);

            }

        }catch (Exception e){
            e.printStackTrace();
            return SqlResult.error(this.getClass().toString(),e);
        }
        return SqlResult.ok(null,null);
    }

    /**
     * 处理预出库
     * @param hashMap
     * @param item
     * @return
     */
    public void dealWillOut(HashMap<String,HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>>> hashMap,GatherIssueZuZhuangInfo item){
        HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>> map1 = hashMap.get(item.getProcessProductName());

        //定位产品
        if (map1 != null && map1.size() > 0){
            dealQuantityItemCode(map1,item);
        }
    }


    /**
     * 处理产品信息
     * @param map1
     * @param item
     */
    public void  dealQuantityItemCode(HashMap<String,HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>>> map1, GatherIssueZuZhuangInfo item){
        if (map1.size() == 0){
            return;
        }
        HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>> map2 = map1.get(item.getItemCode());

        //定位仓库
        if (map2 != null && map2.size() > 0){
            dealQuantityWarehouse(map2,item);
        }

        //如果已经预出库数量不满足 组装半成品数量
        if (item.getQuantity().floatValue() != 0){
            Set<String> keys =  map1.keySet();
            for (String key: keys) {
                map2 = map1.get(key);
                dealQuantityWarehouse(map2,item);
                //领料数量处理完
                if (item.getQuantity().floatValue() == 0){
                    return;
                }
            }
        }
    }


    /**
     * 处理仓库信息
     * @param map2
     * @param item
     */
    public void  dealQuantityWarehouse(HashMap<String,HashMap<String,ItemNeedStockWillOutInfo>> map2, GatherIssueZuZhuangInfo item){
        if (map2.size() == 0){
            return;
        }
        HashMap<String,ItemNeedStockWillOutInfo> map3 = map2.get(item.getWarehouseCode());

        //定位仓库
        if (map3 != null && map3.size() > 0){
            dealQuantityBatchCode(map3,item);
        }

        //如果已经预出库数量不满足 组装半成品数量
        if (item.getQuantity().floatValue() != 0){
            Set<String> keys =  map2.keySet();
            for (String key: keys) {
                map3 = map2.get(key);
                dealQuantityBatchCode(map3,item);
                //领料数量处理完
                if (item.getQuantity().floatValue() == 0){
                    return;
                }
            }
        }
    }

    /**
     * 处理批次信息
     * @param map3
     * @param item
     */
    public void dealQuantityBatchCode(HashMap<String,ItemNeedStockWillOutInfo> map3, GatherIssueZuZhuangInfo item){
        if (map3.size() == 0){
            return;
        }
        ItemNeedStockWillOutInfo info = map3.get(item.getBatchCode());
        //定位批次
        if (info != null){
            dealQuantity(map3,info,item);
        }

        //如果已经预出库数量不满足 组装半成品数量
        if (item.getQuantity().floatValue() != 0){
            Set<String> keys =  map3.keySet();
            for (String key: keys) {
                info = map3.get(key);
                dealQuantity(map3,info,item);
                //领料数量处理完
                if (item.getQuantity().floatValue() == 0){
                    break;
                }
            }
        }

    }

    /**
     * 处理预出库信息
     * @param map3
     * @param info
     * @param item
     */
    public void dealQuantity(HashMap<String,ItemNeedStockWillOutInfo> map3, ItemNeedStockWillOutInfo info,GatherIssueZuZhuangInfo item){
        if (info.getQuantity().floatValue() >= item.getQuantity().floatValue()){
            //数据库：修改的预出库数量
            WmStockWillOut willOut = new WmStockWillOut();
            willOut.setQuantity(info.getQuantity().floatValue() - item.getQuantity().floatValue());
            willOut.setRecordId(info.getRecordId());
            updateById(willOut);
            //本地：修改预出库缓存
            info.setQuantity(willOut.getQuantity());
            //本地修改：领料数量
            item.setQuantity(BigDecimal.valueOf(0));
        }else {
            //数据库：修改的预出库数量
            WmStockWillOut willOut = new WmStockWillOut();
            willOut.setQuantity(0);
            willOut.setRecordId(info.getRecordId());
            updateById(willOut);
            //本地：删除预出库缓存
            map3.remove(info);
            //本地修改：领料数量
            float needCount = item.getQuantity().floatValue() - info.getQuantity().floatValue();
            item.setQuantity(BigDecimal.valueOf(needCount));
        }
    }


}
